home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i053: 2.11 News Source, Part03/09
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: seismo!rick (Rick Adams)
- Mod.sources: Volume 7, Issue 53
- Archive-name: 2.11news/Part13
-
- # To extract, sh this file
- #
- # news 2.11 source part 3 of 9
- #
- if test ! -d src
- then
- mkdir src
- fi
- echo x - src/inews.c 1>&2
- sed 's/.//' >src/inews.c <<'*-*-END-of-src/inews.c-*-*'
- -/*
- - * This software is Copyright (c) 1986 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - * inews - insert, receive, and transmit news articles.
- - *
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)inews.c 2.69 10/30/86";
- -#endif /* SCCSID */
- -
- -#include "iparams.h"
- -#include <errno.h>
- -
- -#ifdef BSD4_2
- -# include <sys/dir.h>
- -# include <sys/file.h>
- -#else /* !BSD4_2 */
- -# include "ndir.h"
- -# ifdef USG
- -# include <fcntl.h>
- -# endif /* USG */
- -# ifdef LOCKF
- -# include <unistd.h>
- -# endif /* LOCKF */
- -#endif /* !BSD4_2 */
- -/* local defines for inews */
- -
- -#define OPTION 0 /* pick up an option string */
- -#define STRING 1 /* pick up a string of arguments */
- -
- -#define UNKNOWN 0001 /* possible modes for news program */
- -#define UNPROC 0002 /* Unprocessed input */
- -#define PROC 0004 /* Processed input */
- -#define CONTROL 0010 /* Control Message */
- -#define CREATENG 0020 /* Create a new newsgroup */
- -
- -char forgedname[NAMELEN]; /* A user specified -f option. */
- -int spool_news = FALSE;
- -extern char histline[];
- -/* Fake sys line in case they forget their own system */
- -struct srec dummy_srec = { "MEMEME", "", "all", "", "" };
- -
- -char *Progname = "inews"; /* used by xerror to identify failing program */
- -
- -struct { /* options table. */
- - char optlet; /* option character. */
- - char filchar; /* if to pickup string, fill character. */
- - int flag; /* TRUE if have seen this opt. */
- - int oldmode; /* OR of legal input modes. */
- - int newmode; /* output mode. */
- - char *buf; /* string buffer */
- -} *optpt, options[] = { /*
- -optlet filchar flag oldmode newmode buf */
- -'t', ' ', FALSE, UNPROC, UNKNOWN, header.title,
- -'n', NGDELIM, FALSE, UNPROC, UNKNOWN, header.nbuf,
- -'d', '\0', FALSE, UNPROC, UNKNOWN, header.distribution,
- -'e', ' ', FALSE, UNPROC, UNKNOWN, header.expdate,
- -'p', '\0', FALSE, UNKNOWN|PROC, PROC, filename,
- -'f', '\0', FALSE, UNPROC, UNKNOWN, forgedname,
- -'F', ' ', FALSE, UNPROC, UNKNOWN, header.followid,
- -'c', ' ', FALSE, UNKNOWN,UNKNOWN, header.ctlmsg,
- -'C', ' ', FALSE, UNKNOWN,CREATENG, header.ctlmsg,
- -#define hflag options[9].flag
- -'h', '\0', FALSE, UNPROC, UNKNOWN, filename,
- -#define oflag options[10].flag
- -'o', '\0', FALSE, UNPROC, UNKNOWN, header.organization,
- -#define Mflag options[11].flag
- -'M', '\0', FALSE, UNPROC, UNKNOWN, filename,
- -'a', '\0', FALSE, UNPROC, UNKNOWN, header.approved,
- -'U', '\0', FALSE, PROC, PROC, filename,
- -'S', '\0', FALSE, UNKNOWN|PROC, UNPROC, filename,
- -'x', '\0', FALSE, UNPROC, UNKNOWN, not_here,
- -'r', '\0', FALSE, UNPROC, UNKNOWN, header.replyto,
- -'\0', '\0', 0, 0, 0, (char *)NULL
- -};
- -
- -FILE *mailhdr();
- -extern int errno;
- -
- -struct timeb Now;
- -
- -/*
- - * Authors:
- - * Matt Glickman glickman@ucbarpa.Berkeley.ARPA
- - * Mark Horton mark@cbosgd.UUCP
- - * Stephen Daniels swd@mcnc.UUCP
- - * Tom Truscott trt@duke.UUCP
- - * Rick Adams rick@seismo.CSS.GOV
- - * IHCC version adapted by:
- - * Larry Marek larry@ihuxf.UUCP
- - */
- -main(argc, argv)
- -int argc;
- -register char **argv;
- -{
- - int state; /* which type of argument to pick up */
- - int tlen, len; /* temps for string processing routine */
- - register char *ptr; /* pointer to rest of buffer */
- - int filchar; /* fill character (state = STRING) */
- - char *user = NULL, *home = NULL; /* environment temps */
- - struct passwd *pw; /* struct for pw lookup */
- - struct group *gp; /* struct for group lookup */
- - register int i;
- - FILE *mfd; /* mail file file-descriptor */
- - char cbuf[BUFLEN]; /* command buffer */
- -
- - /* uuxqt doesn't close all it's files */
- - for (i = 3; !close(i); i++)
- - ;
- - /* set up defaults and initialize. */
- - mode = UNKNOWN;
- - infp = stdin;
- - pathinit();
- - ptr = rindex(*argv, '/');
- - if (!ptr)
- - ptr = *argv - 1;
- - actfp = xfopen(ACTIVE, "r+");
- -#ifdef BSD4_2
- - if (flock(fileno(actfp), LOCK_SH|LOCK_NB) < 0 && errno == EWOULDBLOCK)
- -#else /* !BSD4_2 */
- -#ifdef LOCKF
- - if (lockf(fileno(actfp), F_TLOCK, 0) < 0 && errno == EAGAIN)
- -#else /* !LOCKF */
- - sprintf(bfr, "%s.lock", ACTIVE);
- - if (LINK(ACTIVE,bfr) < 0 && errno == EEXIST)
- -#endif /* V7 */
- -#endif /* !BSD4_2 */
- - spool_news = TRUE;
- - else {
- -#ifdef SPOOLNEWS
- - if (argc > 1 && !strcmp(*(argv+1), "-S")) {
- - argc--;
- - argv++;
- - } else
- - spool_news = TRUE;
- -
- -#endif /* SPOOLNEWS */
- -#if !defined(BSD4_2) && !defined(LOCKF)
- - (void) UNLINK(bfr);
- -#endif /* !BSD4_2 && !LOCKF */
- - }
- - if (argc > 1 && !strcmp(*(argv+1), "-U")) {
- - dounspool();
- - /* NOT REACHED */
- - }
- -
- - if (!strncmp(ptr+1, "rnews", 5)) {
- - mode = PROC;
- - if (spool_news) {
- - dospool((char *)NULL, FALSE);
- - /* NOT REACHED */
- - }
- -#ifdef NICENESS
- - nice(NICENESS);
- -#endif /* NICENESS */
- - } else
- - if (argc < 2)
- - goto usage;
- -
- - state = OPTION;
- - header.title[0] = header.nbuf[0] = filename[0] = '\0';
- -
- - /* check for existence of special files */
- - if (!rwaccess(ARTFILE)) {
- - mfd = mailhdr((struct hbuf *)NULL, exists(ARTFILE) ? "Unwritable files!" : "Missing files!");
- - if (mfd != NULL) {
- -#ifdef HIDDENNET
- - fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
- -#else /* !HIDDENNET */
- - fprintf(mfd,"System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ARTFILE);
- -#endif /* !HIDDENNET */
- - (void) sprintf(cbuf, "touch %s;chmod 666 %s", ARTFILE, ARTFILE);
- - (void) system(cbuf);
- - if (rwaccess(ARTFILE))
- - fprintf(mfd, "The problem has been taken care of.\n");
- - else
- - fprintf(mfd, "Corrective action failed - check suid bits.\n");
- - (void) mclose(mfd);
- - }
- - }
- - if (!rwaccess(ACTIVE)) {
- - mfd = mailhdr((struct hbuf *)NULL, exists(ACTIVE) ? "Unwritable files!" : "Missing files!");
- - if (mfd != NULL) {
- -#ifdef HIDDENNET
- - fprintf(mfd,"System: %s.%s\n\nThere was a problem with %s!!\n", LOCALSYSNAME, FULLSYSNAME, ARTFILE);
- -#else /* !HIDDENNET */
- - fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n", FULLSYSNAME, ACTIVE);
- -#endif /* !HIDDENNET */
- - (void) sprintf(cbuf, "touch %s;chmod 666 %s", ACTIVE, ACTIVE);
- - (void) system(cbuf);
- - if (rwaccess(ACTIVE))
- - fprintf(mfd, "The problem has been taken care of.\n");
- - else
- - fprintf(mfd, "Corrective action failed - check suid bits.\n");
- - (void) mclose(mfd);
- - }
- - }
- - SigTrap = FALSE; /* true if a signal has been caught */
- - if (mode != PROC) {
- - (void) signal(SIGHUP, onsig);
- - (void) signal(SIGINT, onsig);
- - }
- - savmask = umask(N_UMASK); /* set up mask */
- - uid = getuid();
- - gid = getgid();
- - duid = geteuid();
- - dgid = getegid();
- - (void) ftime(&Now);
- - if (uid == 0 && duid == 0) {
- - /*
- - * Must go through with this kludge since
- - * some systems do not honor the setuid bit
- - * when root invokes a setuid program.
- - */
- - if ((pw = getpwnam(NEWSUSR)) == NULL)
- - xerror("Cannot get NEWSU pw entry");
- -
- - duid = pw->pw_uid;
- - if ((gp = getgrnam(NEWSGRP)) == NULL)
- - xerror("Cannot get NEWSG gr entry");
- - dgid = gp->gr_gid;
- - (void) setgid(dgid);
- - (void) setuid(duid);
- - }
- -
- -#ifndef IHCC
- - /*
- - * We force the use of 'getuser()' to prevent forgery of articles
- - * by just changing $LOGNAME
- - */
- - if (isatty(fileno(stderr))) {
- - if ((user = getenv("USER")) == NULL)
- - user = getenv("LOGNAME");
- - if ((home = getenv("HOME")) == NULL)
- - home = getenv("LOGDIR");
- - }
- -#endif
- - if (user == NULL || home == NULL)
- - getuser();
- - else {
- - if (username == NULL || username[0] == 0) {
- - username = AllocCpy(user);
- - }
- - userhome = AllocCpy(home);
- - }
- - getuser();
- -
- - /* loop once per arg. */
- -
- - ++argv; /* skip first arg, which is prog name. */
- -
- - while (--argc) {
- - if (state == OPTION) {
- - if (**argv != '-') {
- - xerror("Bad option string \"%s\"", *argv);
- - }
- - while (*++*argv != '\0') {
- - for (optpt = options; optpt->optlet != '\0'; ++optpt) {
- - if (optpt->optlet == **argv)
- - goto found;
- - }
- - /* unknown option letter */
- -usage:
- - fprintf(stderr, "usage: inews -t title");
- - fprintf(stderr, " [ -n newsgroups ]");
- - fprintf(stderr, " [ -e expiration date ]\n");
- - fprintf(stderr, "\t[ -f sender]\n\n");
- - xxit(1);
- -
- - found:;
- - if (optpt->flag == TRUE || (mode != UNKNOWN &&
- - (mode&optpt->oldmode) == 0)) {
- - xerror("Bad %c option", **argv);
- - }
- - if (mode == UNKNOWN)
- - mode = optpt->newmode;
- - filchar = optpt->filchar;
- - optpt->flag = TRUE;
- - state = STRING;
- - ptr = optpt->buf;
- - len = BUFLEN;
- - }
- -
- - argv++; /* done with this option arg. */
- -
- - } else {
- -
- - /*
- - * Pick up a piece of a string and put it into
- - * the appropriate buffer.
- - */
- - if (**argv == '-') {
- - state = OPTION;
- - argc++; /* uncount this arg. */
- - continue;
- - }
- -
- - if ((tlen = strlen(*argv)) >= len)
- - xerror("Argument string too long");
- - (void) strcpy(ptr, *argv++);
- - ptr += tlen;
- - if (*(ptr-1) != filchar)
- - *ptr++ = filchar;
- - len -= tlen + 1;
- - *ptr = '\0';
- - }
- - }
- -
- - /*
- - * ALL of the command line has now been processed. (!)
- - */
- -
- - if (*filename) {
- - (void) fclose(stdin);
- - infp = freopen(filename, "r", stdin);
- - if (infp == NULL)
- - xerror("freopen(%s): %s", filename, errmsg(errno));
- - } else
- - infp = stdin;
- -
- - tty = isatty(fileno(infp));
- -
- - if (mode == CREATENG)
- - createng();
- -
- - if (header.ctlmsg[0] != '\0' && header.title[0] == '\0')
- - (void) strcpy(header.title, header.ctlmsg);
- -
- - if (*header.nbuf) {
- - lcase(header.nbuf);
- - ptr = index(header.nbuf, '\0');
- - if (ptr[-1] == NGDELIM)
- - *--ptr = '\0';
- - }
- - (void) nstrip(header.title);
- - (void) nstrip(header.expdate);
- - (void) nstrip(header.followid);
- - if (mode != PROC) {
- - if (hflag) {
- - header.path[0] = '\0';
- - (void) hread(&header, infp, FALSE);
- - /* there are certain fields we won't let him specify. */
- - if (header.from[0])
- - (void) strcpy(forgedname, header.from);
- - if (!header.approved[0])
- - Mflag = FALSE;
- - header.from[0] = '\0';
- - header.sender[0] = '\0';
- - if (header.subdate[0] && cgtdate(header.subdate) < 0)
- - header.subdate[0] = '\0';
- - }
- -
- - if (header.ident[0] == '\0')
- - getident(&header);
- -
- - if (forgedname[0]) {
- - register char *p1;
- - if (Mflag)
- - sprintf(header.path, "%s!%s",
- - FULLSYSNAME, username);
- - else if (!header.path[0]) {
- - (void) strcpy(header.path, forgedname);
- -
- - if ((p1 = strpbrk(header.path, "@ (<")) != NULL)
- - *p1 = '\0';
- - }
- - if (!Mflag && !strpbrk(forgedname, "@ (<"))
- - (void) sprintf(header.from,"%s@%s%s",
- - forgedname, FULLSYSNAME, MYDOMAIN);
- - else
- - (void) strncpy(header.from, forgedname, BUFLEN);
- -
- - (void) sprintf(header.sender, "%s@%s%s",
- - username, FULLSYSNAME, MYDOMAIN);
- - } else {
- - gensender(&header, username);
- - }
- -#ifdef MYORG
- - if (header.organization[0] == '\0' && !Mflag &&
- - header.sender[0] == '\0') {
- - strncpy(header.organization, MYORG, BUFLEN);
- - if (strncmp(header.organization, "Frobozz", 7) == 0)
- - header.organization[0] = '\0';
- - if (ptr = getenv("ORGANIZATION"))
- - strncpy(header.organization, ptr, BUFLEN);
- - /*
- - * Note that the organization can also be turned off by
- - * setting it to the null string, either in MYORG or
- - * $ORGANIZATION in the environment.
- - */
- - if (header.organization[0] == '/') {
- - mfd = fopen(header.organization, "r");
- - if (mfd) {
- - (void) fgets(header.organization, sizeof header.organization, mfd);
- - (void) fclose(mfd);
- - } else {
- - header.organization[0] = '\0';
- - logerr("Couldn't open %s",
- - header.organization);
- - }
- - ptr = index(header.organization, '\n');
- - if (ptr)
- - *ptr = '\0';
- - }
- - }
- -#endif /* MYORG */
- - }
- -
- - /* Authorize newsgroups. */
- - if (mode == PROC) {
- -#ifdef BATCH
- - checkbatch();
- -#endif /* BATCH */
- - (void) signal(SIGHUP, SIG_IGN);
- - (void) signal(SIGINT, SIG_IGN);
- - (void) signal(SIGQUIT, SIG_IGN);
- - header.ident[0] = '\0';
- - if (hread(&header, infp, TRUE) == NULL)
- - error("Inbound news is garbled");
- - input();
- - }
- - /* always check history */
- -
- - if (history(&header)) {
- - log("Duplicate article %s rejected. Path: %s",
- - header.ident, header.path);
- - xxit(0);
- - }
- -
- - /* Easy way to make control messages, since all.all.ctl is unblessed */
- - if (mode != PROC && prefix(header.title, "cmsg ") && header.ctlmsg[0] == 0)
- - (void) strcpy(header.ctlmsg, &header.title[5]);
- - is_ctl = mode != CREATENG &&
- - (ngmatch(header.nbuf, "all.all.ctl,") || header.ctlmsg[0]);
- -#ifdef DEBUG
- - fprintf(stderr,"is_ctl set to %d\n", is_ctl);
- -#endif
- -
- - if (mode != CREATENG) {
- - if (!*header.title)
- - error("No title, ng %s from %s", header.nbuf,
- - header.from);
- - if (!*header.nbuf)
- - (void) strcpy(header.nbuf, DFLTNG);
- - }
- -
- - if (mode <= UNPROC) {
- -#ifdef FASCIST
- - if (uid && uid != ROOTID && fascist(user, header.nbuf))
- - xerror("User %s is not authorized to post to newsgroup %s",
- - user, header.nbuf);
- -#endif /* FASCIST */
- - ctlcheck();
- - }
- -
- - if (mode == CREATENG)
- - createng();
- -
- - /* Determine input. */
- - if (mode != PROC)
- - input();
- - if (header.intnumlines == 0 && !is_ctl)
- - error("%s rejected: no text lines", header.ident);
- -
- - dates(&header);
- -
- - /* Do the actual insertion. */
- - insert();
- -}
- -
- -dospool(batchcmd, dolhwrite)
- -char *batchcmd;
- -int dolhwrite;
- -{
- - register int c;
- - register FILE *sp;
- - register struct tm *tp;
- - time_t t;
- - char buf[BUFLEN];
- - extern struct tm *gmtime();
- -
- - (void) time(&t);
- - tp = gmtime(&t);
- - /* This file name "has to" be unique (right?) */
- -#ifdef USG
- - (void) sprintf(buf, "%s/.rnews/%2.2d%2.2d%2.2d%2.2d%2.2d%x",
- -#else
- -#ifdef VMS
- - /* Eunice doesn't like dots in directory names */
- - (void) sprintf(buf, "%s/+rnews/%02d%02d%02d%02d%02d%x",
- -#else /* V7 */
- - (void) sprintf(buf, "%s/.rnews/%02d%02d%02d%02d%02d%x",
- -#endif /* V7 */
- -#endif /* VMS */
- - SPOOLDIR,
- - tp->tm_year, tp->tm_mon+1, tp->tm_mday,
- - tp->tm_hour, tp->tm_min, getpid());
- - sp = xfopen(buf, "w");
- - if (batchcmd != NULL)
- - fprintf(sp, "%s\n", batchcmd);
- - if (dolhwrite)
- - lhwrite(&header, sp);
- - while ((c = getc(infp)) != EOF)
- - putc(c, sp);
- - fclose(sp);
- - xxit(0);
- - /* NOTREACHED */
- -}
- -
- -/*
- - * Create a newsgroup
- - */
- -createng()
- -{
- - register char *cp;
- -
- - /*
- - * Only certain users are allowed to create newsgroups
- - */
- - if (uid != ROOTID && uid != duid && uid) {
- - fprintf(stderr, "Please contact one of the local netnews people\n\tto create this group for you");
- - xxit(1);
- - }
- - if (header.distribution[0] == '\0')
- -#ifdef ORGDISTRIB
- - strcpy(header.distribution, ORGDISTRIB);
- -#else /* !ORGDISTRIB */
- - strcpy(header.distribution, "local");
- -#endif /* !ORGDISTRIB */
- -
- - (void) strcpy(header.nbuf, header.ctlmsg);
- - if ((cp=index(header.nbuf, ' ')) != NULL)
- - *cp = '\0';
- -
- - if (header.approved[0] == '\0')
- - (void) sprintf(header.approved, "%s@%s%s",
- - username, FULLSYSNAME, MYDOMAIN);
- - (void) sprintf(bfr, "%s/inews -n %s.ctl -c newgroup %s -d %s -a \"%s\"",
- - LIB, header.nbuf, header.ctlmsg, header.distribution,
- - header.approved);
- - if (tty) {
- - printf("Please type in a paragraph describing the new newsgroup.\n");
- - printf("End with control D as usual.\n");
- - }
- - printf("%s\n", bfr);
- - (void) fflush(stdout);
- - (void) system(bfr);
- - exit(0);
- - /*NOTREACHED*/
- -}
- -
- -char firstbufname[BUFLEN];
- -/*
- - * Link ARTICLE into dir for ngname and update active file.
- - */
- -long
- -localize(ngname)
- -char *ngname;
- -{
- - char afline[BUFLEN];
- - long ngsize;
- - long fpos;
- - int e;
- - char *cp;
- -
- - lock();
- - (void) rewind(actfp); clearerr(actfp);
- -
- - for(;;) {
- - fpos = ftell(actfp);
- - if (fgets(afline, sizeof afline, actfp) == NULL) {
- - unlock();
- - logerr("Can't find \"%s\" in active file", ngname);
- - return FALSE; /* No such newsgroup locally */
- - }
- - if (prefix(afline, ngname)) {
- - (void) sscanf(afline, "%s %ld", bfr, &ngsize);
- - if (strcmp(bfr, ngname) == 0) {
- - if (ngsize < 0 || ngsize > 99998) {
- - logerr("found bad ngsize %ld ng %s, setting to 1", ngsize, bfr);
- - ngsize = 1;
- - }
- - break;
- - }
- - }
- - }
- - for (;;) {
- - cp = dirname(ngname);
- -
- - (void) sprintf(bfr, "%s/%ld", cp, ngsize+1);
- -#ifdef VMS
- - /*
- - * The effect of this code is to store the article in the first
- - * newsgroup's directory and to put symbolic links elsewhere.
- - * If this is the first group, firstbufname is not yet filled
- - * in. It should be portable to other link-less systems.
- - * epimass!jbuck
- - */
- - if (firstbufname[0]) {
- - if (vmslink(firstbufname, bfr) == 0)
- - break;
- - } else if (rename(ARTICLE, bfr) == 0)
- - break;
- -#else /* !VMS */
- - if (link(ARTICLE, bfr) == 0)
- - break;
- -#endif /* !VMS */
- - if (!exists(cp))
- - mknewsg(cp, ngname);
- -#ifdef VMS
- - if (firstbufname[0]) {
- - if (vmslink(firstbufname, bfr) == 0)
- - break;
- - } else if (rename(ARTICLE, bfr) == 0)
- - break;
- -#else /* !VMS */
- - if (link(ARTICLE, bfr) == 0)
- - break;
- -#endif /* !VMS */
- - e = errno; /* keep log from clobbering it */
- - log("Cannot install article as %s: %s", bfr, errmsg(errno));
- - if (e != EEXIST) {
- - logerr("Link into %s failed (%s); check dir permissions.",
- - bfr, errmsg(e));
- - unlock();
- - return FALSE;
- - }
- - ngsize++;
- - }
- -
- - /*
- - * This works around a bug in the 4.1bsd stdio
- - * on fseeks to non even offsets in r+w files
- - */
- - if (fpos&1)
- - (void) rewind(actfp);
- -
- - (void) fseek(actfp, fpos, 0);
- -#ifdef USG
- - /*
- - * U G L Y K L U D G E
- - * This utter piece of tripe is the only way I know of to get
- - * around the fact that ATT BROKE standard IO in System 5.2.
- - * Basically, you can't open a file for "r+" and then try and
- - * write to it. This works on all "real" USGUnix systems, It will
- - * probably break on some obscure look alike that doesnt use the
- - * real ATT stdio.h
- - * Don't blame me, blame ATT. stdio should have already done the
- - * following line for us, but it doesn't
- - */
- - actfp->_flag |= _IOWRT;
- -#endif /* USG */
- - /* Has to be same size as old because of %05d.
- - * This will overflow with 99999 articles.
- - */
- - fprintf(actfp, "%s %05ld", ngname, ngsize+1);
- - (void) fflush(actfp);
- - if (ferror(actfp))
- - xerror("Active file write failed");
- - unlock();
- - if (firstbufname[0] == '\0')
- - (void) strcpy(firstbufname, bfr);
- - (void) sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
- - addhist(bfr);
- - return ngsize+1;
- -}
- -
- -/*
- - * Localize for each newsgroup and broadcast.
- - */
- -insert()
- -{
- - register char *ptr;
- - register FILE *tfp;
- - register int c;
- - struct srec srec; /* struct for sys file lookup */
- - struct tm *tm, *gmtime();
- - int is_invalid = FALSE;
- - int exitcode = 0;
- - long now;
- -#ifdef DOXREFS
- - register char *nextref = header.xref;
- -#endif /* DOXREFS */
- -
- - /* Clean up Newsgroups: line */
- - if (!is_ctl && mode != CREATENG)
- - is_invalid = ngfcheck(mode == PROC);
- -
- - (void) time(&now);
- - tm = gmtime(&now);
- - if (header.expdate[0])
- - addhist(" ");
- -#ifdef USG
- - sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d\t",
- -#else /* !USG */
- - sprintf(bfr,"%02d/%02d/%d %02d:%02d\t",
- -#endif /* !USG */
- - tm->tm_mon+1, tm->tm_mday, tm->tm_year,tm->tm_hour, tm->tm_min);
- - addhist(bfr);
- - log("%s %s ng %s subj '%s' from %s",
- - spool_news ? "queued" : (mode==PROC ? "received" : "posted"),
- - header.ident, header.nbuf, header.title, header.from);
- -
- - /* Write article to temp file. */
- - tfp = xfopen(mktemp(ARTICLE), "w");
- -
- - if (is_invalid) {
- - logerr("No valid newsgroups found, moved to junk");
- - if (localize("junk"))
- - savehist(histline);
- - exitcode = 1;
- - goto writeout;
- - }
- -
- -#ifdef ZAPNOTES
- - if (strcmp(header.title, "Re: Orphaned Response") == 0) {
- - logerr("Orphaned Response, moved to junk");
- - if (localize("junk"))
- - savehist(histline);
- - exitcode = 1;
- - goto writeout;
- - }
- -#endif /* ZAPNOTES */
- -
- - if (time((time_t *)0) > (cgtdate(header.subdate) + HISTEXP) ){
- - logerr("Article too old, moved to junk");
- - if (localize("junk"))
- - savehist(histline);
- - exitcode = 1;
- - goto writeout;
- - }
- -
- - if (is_mod[0] != '\0' /* one of the groups is moderated */
- - && header.approved[0] == '\0') { /* and unapproved */
- - struct hbuf mhdr;
- - FILE *mfd;
- - register char *p;
- - char modadd[BUFLEN];
- -#ifdef DONTFOWARD
- - if(mode == PROC) {
- - logerr("Unapproved article in moderated group %s",
- - is_mod);
- - if (localize("junk"))
- - savehist(histline);
- - goto writeout;
- - }
- -#endif /* DONTFORWARD */
- - fprintf(stderr,"%s is moderated and may not be posted to",
- - is_mod);
- - fprintf(stderr," directly.\nYour article is being mailed to");
- - fprintf(stderr," the moderator who will post it for you.\n");
- - /* Let's find a path to the backbone */
- - sprintf(bfr, "%s/mailpaths", LIBDIR);
- - mfd = xfopen(bfr, "r");
- - do {
- - if (fgets(bfr, sizeof bfr, mfd) == NULL)
- - xerror("Can't find backbone in %s/mailpaths",
- - LIBDIR);
- - } while (!prefix(bfr, "backbone"));
- - if (sscanf(bfr, "%*s %s", modadd) != 1)
- - xerror("backbone address corrupted");
- - /* fake a header for mailhdr */
- - mhdr.from[0] = '\0';
- - mhdr.replyto[0] = '\0';
- - p = is_mod;
- - while (*++p)
- - if (*p == '.')
- - *p = '-';
- - sprintf(bfr, "Submission for %s", is_mod);
- - sprintf(mhdr.path, modadd, is_mod);
- - mfd = mailhdr(&mhdr, bfr);
- - if (mfd == NULL)
- - xerror("Can't send mail to %s", mhdr.path);
- - lhwrite(&header, mfd);
- - while ((c = getc(infp)) != EOF)
- - putc(c, mfd);
- - mclose(mfd);
- - log("Article mailed to %s", mhdr.path);
- - xxit(0);
- - }
- -
- - if (spool_news && mode != PROC) {
- - fprintf(stderr,"Your article has been spooled for later processing.\n");
- - dospool((char *)NULL, TRUE);
- - /* NOT REACHED */
- - }
- -
- - if (is_ctl) {
- - exitcode = control(&header);
- - if (localize("control") && exitcode != 0)
- - savehist(histline);
- - } else {
- - if (s_find(&srec, FULLSYSNAME) == FALSE) {
- - logerr("Cannot find my name '%s' in %s", FULLSYSNAME, SUBFILE);
- - srec = dummy_srec;
- - }
- -#ifdef DOXREFS
- - (void) strncpy(nextref, FULLSYSNAME, BUFLEN);
- -#endif /* DOXREFS */
- - for (ptr = nbuf; *ptr;) {
- - if (ngmatch(ptr,srec.s_nbuf) || index(ptr,'.') == NULL){
- -#ifdef DOXREFS
- - while (*nextref++)
- - ;
- - (void) sprintf(--nextref, " %s:%ld", ptr, localize(ptr));
- -#else /* !DOXREFS */
- - (void) localize(ptr);
- -#endif /* !DOXREFS */
- - }
- - while (*ptr++)
- - ;
- - }
- - if (firstbufname[0] == '\0') {
- - logerr("Newsgroups in active, but not sys");
- - (void) localize("junk");
- - }
- - }
- -#ifdef DOXREFS
- - if (index(header.nbuf, NGDELIM) == NULL)
- - header.xref[0] = '\0';
- -#endif /* DOXREFS */
- -
- -writeout:
- - /* Part 1 of kludge to get around article truncation problem */
- - if ( (c=getc(infp)) != EOF) {
- - ungetc(c, infp);
- - if (c == ' ' || c == '\t') {
- - header.intnumlines++;
- - (void) sprintf(header.numlines, "%d",
- - header.intnumlines);
- - }
- - }
- - /* End of part 1 */
- - if (header.expdate[0] != '\0' && mode != PROC) {
- - /* Make sure it's fully qualified */
- - long t = cgtdate(header.expdate);
- - strcpy(header.expdate, arpadate(&t));
- - }
- -
- - lhwrite(&header, tfp);
- - if ((c = getc(infp)) != EOF) {
- - /* Part 2 of kludge to get around article truncation problem */
- - if (c == ' ' || c == '\t' )
- - putc('\n', tfp);
- - /* End of part 2 */
- - ungetc(c, infp);
- - while (fgets(bfr, BUFLEN, infp) != NULL)
- - fputs(bfr, tfp);
- - if (bfr[strlen(bfr)-1] != '\n')
- - putc('\n',tfp);
- - }
- - if (ferror(tfp))
- - xerror("Write failed for temp file");
- - (void) fclose(tfp);
- - (void) fclose(infp);
- - if(exitcode == 0) {
- - int pid;
- - /* article has passed all the checks, so work in background */
- - if (mode != PROC)
- - if ((pid=vfork()) < 0)
- - xerror("Can't fork");
- - else if (pid > 0)
- - exit(0);
- -#ifdef SIGTTOU
- - signal(SIGTTOU, SIG_IGN);
- -#endif /* SIGTTOU */
- - savehist(histline);
- - broadcast();
- - }
- - xxit(mode == PROC ? 0 : exitcode);
- -}
- -
- -input()
- -{
- - register char *cp;
- - register int c;
- - register int empty = TRUE;
- - FILE *tmpfp;
- - int consec_newlines = 0;
- - int linecount = 0;
- - int linserted = 0;
- -
- - tmpfp = xfopen(mktemp(INFILE), "w");
- - while (!SigTrap && fgets(bfr, BUFLEN, infp) != NULL) {
- - if (mode == PROC) { /* zap trailing empty lines */
- -#ifdef ZAPNOTES
- - if (empty && bfr[0] == '#' && bfr[2] == ':'
- - && header.nf_id[0] == '\0'
- - && header.nf_from[0] == '\0' ) {
- - (void) strcpy(header.nf_id, bfr);
- - (void) nstrip(header.nf_id);
- - (void) fgets(bfr, BUFLEN, infp);
- - (void) strcpy(header.nf_from, bfr);
- - (void) nstrip(header.nf_from);
- - (void) fgets(bfr, BUFLEN, infp);
- -
- - if (header.numlines[0]) {
- - header.intnumlines -= 2;
- - (void) sprintf(header.numlines, "%d", header.intnumlines);
- - }
- -
- - /* Strip trailing " - (nf)" */
- - if ((cp = rindex(header.title, '-')) != NULL
- - && !strcmp(--cp, " - (nf)"))
- - *cp = '\0';
- - log("Stripped notes header on %s", header.ident);
- - continue;
- - }
- -#endif /* ZAPNOTES */
- - if (bfr[0] == '\n' ||
- - /* Bandage for older versions of inews */
- - bfr[1] == '\n' && !isascii(bfr[0])) {
- - consec_newlines++; /* count it, in case */
- - continue; /* but don't write it*/
- - }
- - /* foo! a non-empty line. write out all saved lines. */
- - while (consec_newlines > 0) {
- - putc('\n', tmpfp);
- - consec_newlines--;
- - linecount++;
- - }
- - }
- - if (mode != PROC && tty && strcmp(bfr, ".\n") == 0)
- - break;
- - for (cp = bfr; c = toascii(*cp); cp++) {
- - if (isprint(c) || isspace(c) || c == '\b')
- - putc(c, tmpfp);
- - if (c == '\n')
- - linecount++;
- - }
- - if (bfr[0] == '>')
- - linserted++;
- - empty = FALSE;
- - }
- - if (*filename)
- - (void) fclose(infp);
- - if (mode != PROC && linserted > (linecount-linserted))
- - error("Article rejected: %s included more text than new text",
- - username);
- -
- - if (mode != PROC && !is_ctl && header.sender[0] == '\0') {
- - int siglines = 0;
- - char sbuf[BUFLEN];
- - (void) sprintf(bfr, "%s/%s", userhome, ".signature");
- - if (access(bfr, 4) == 0) {
- - if ((infp = fopen(bfr, "r")) == NULL) {
- - (void) fprintf(stderr,
- - "inews: \"%s\" left off (must be readable by \"inews\" owner)\n", bfr);
- - goto finish;
- - }
- -
- - while (fgets(sbuf, sizeof sbuf, infp) != NULL)
- - if (++siglines > 4)
- - break;
- - if (siglines > 4)
- - fprintf(stderr,".signature not included (> 4 lines)\n");
- - else {
- - rewind(infp);
- - fprintf(tmpfp, "-- \n"); /* To separate */
- - linecount++;
- - while ((c = getc(infp)) != EOF) {
- - putc(c, tmpfp);
- - if (c == '\n')
- - linecount++;
- - }
- - }
- - (void) fclose(infp);
- - }
- - }
- -
- -finish:
- - if (ferror(tmpfp))
- - xerror("write failed to temp file");
- - (void) fclose(tmpfp);
- - if (SigTrap) {
- - if (tty)
- - fprintf(stderr, "Interrupt\n");
- - if (tty && !empty)
- - fwait(fsubr(newssave, (char *) NULL, (char *) NULL));
- - if (!tty)
- - log("Blown away by an interrupt %d", SigTrap);
- - xxit(1);
- - }
- - if (tty)
- - fprintf(stderr, "EOT\n");
- - fflush(stdout);
- - infp = fopen(INFILE, "r");
- - if (header.numlines[0]) {
- - /*
- - * Check line count if there's already one attached to
- - * the article. Could make this a fatal error -
- - * throwing it away if it got chopped, in hopes that
- - * another copy will come in later with a correct
- - * line count. But that seems a bit much for now.
- - */
- - if (linecount != header.intnumlines) {
- - if (linecount == 0)
- - error("%s rejected. linecount expected %d, got 0", header.ident, header.intnumlines);
- - if (linecount > header.intnumlines ||
- - linecount+consec_newlines < header.intnumlines)
- - log("linecount expected %d, got %d", header.intnumlines, linecount+consec_newlines);
- - }
- - /* adjust count for blank lines we stripped off */
- - if (consec_newlines) {
- - header.intnumlines -= consec_newlines;
- - if (header.intnumlines < 0 )
- - header.intnumlines = 0; /* paranoia */
- - (void) sprintf(header.numlines, "%d", header.intnumlines);
- - }
- -
- - } else {
- - /* Attach a line count to the article. */
- - header.intnumlines = linecount;
- - (void) sprintf(header.numlines, "%d", linecount);
- - }
- -}
- -
- -/*
- - * Make the directory for a new newsgroup. ngname should be the
- - * full pathname of the directory. Do the other stuff too.
- - * The various games with setuid and chown are to try to make sure
- - * the directory is owned by NEWSUSR and NEWSGRP, which is tough to
- - * do if you aren't root. This will work on a UCB system (which allows
- - * setuid(geteuid()) or a USG system (which allows you to give away files
- - * you own with chown), otherwise you have to change your kernel to allow
- - * one of these things or run with your dirs 777 so that it doesn't matter
- - * who owns them.
- - */
- -mknewsg(fulldir, ngname)
- -char *fulldir;
- -char *ngname;
- -{
- -#ifdef USG
- - register char *p;
- - char parent[200];
- - char sysbuf[200];
- - struct stat sbuf;
- -#endif /* USG */
- -
- - if (ngname == NULL || !isalpha(ngname[0]))
- - xerror("Tried to make illegal newsgroup %s", ngname);
- -
- -#ifdef USG
- - /*
- - * If the parent is 755 the setuid(getuid)
- - * will fail, and since mkdir is suid, and our real uid is random,
- - * the mkdir will fail. So we have to temporarily chmod it to 777.
- - */
- - (void) strcpy(parent, fulldir);
- - while (p = rindex(parent, '/')) {
- - *p = '\0';
- - if (stat(parent, &sbuf) == 0) {
- - (void) chmod(parent, 0777);
- - break;
- - }
- - }
- -#endif /* USG */
- -
- - /* Create the directory */
- - mkparents(fulldir);
- - if (mkdir(fulldir, 0777) < 0)
- - xerror("Cannot mkdir %s: %s", fulldir, errmsg(errno));
- -
- -#ifdef USG
- - (void) chmod(parent, (int)sbuf.st_mode); /* put it back */
- - /*
- - * Give away the directories we just created which were assigned
- - * our real uid.
- - */
- - (void) setuid(uid);
- - (void) chown(fulldir, duid, dgid);
- - (void) strcpy(sysbuf, fulldir);
- - while (p = rindex(sysbuf, '/')) {
- - *p = '\0';
- - /* stop when get to last known good parent */
- - if (strcmp(sysbuf, parent) == 0)
- - break;
- - (void) chown(sysbuf, duid, dgid);
- - }
- - (void) setuid(duid);
- -#endif /* USG */
- -
- - log("make newsgroup %s in dir %s", ngname, fulldir);
- -}
- -
- -/*
- - * If any parent directories of this dir don't exist, create them.
- - */
- -mkparents(dname)
- -char *dname;
- -{
- - char buf[200];
- - register char *p;
- -
- - (void) strcpy(buf, dname);
- - p = rindex(buf, '/');
- - if (p)
- - *p = '\0';
- - if (exists(buf))
- - return;
- - mkparents(buf);
- - if (mkdir(buf, 0777) < 0)
- - xerror("Can not mkdir %s: %s", buf, errmsg(errno));
- -}
- -
- -cancel()
- -{
- - register FILE *fp;
- -
- - log("cancel article %s", filename);
- - fp = fopen(filename, "r");
- - if (fp == NULL) {
- - log("article %s not found", filename);
- - return;
- - }
- - if (hread(&header, fp, TRUE) == NULL)
- - error("Article is garbled.");
- - (void) fclose(fp);
- - (void) unlink(filename);
- -}
- -
- -dounspool()
- -{
- - register DIR *dirp;
- - register struct direct *dir;
- - register int foundsome;
- -#ifdef VMS
- - sprintf(bfr, "%s/+rnews", SPOOLDIR);
- -#else /* !VMS */
- - sprintf(bfr, "%s/.rnews", SPOOLDIR);
- -#endif /* !VMS */
- -
- - if (chdir(bfr) < 0)
- - xerror("chdir(%s):%s", bfr, errmsg(errno));
- -
- - do {
- - foundsome = 0;
- - dirp = opendir(".");
- - if (dirp == NULL) /* Boy are things screwed up */
- - xerror("opendir can't open .:%s", errmsg(errno));
- -
- - while ((dir=readdir(dirp)) != NULL) {
- - if (dir->d_name[0] == '.')
- - continue;
- - sprintf(bfr,"%s -S -p %s", RNEWS, dir->d_name);
- - system(bfr);
- - (void) unlink(dir->d_name);
- - foundsome++;
- - }
- - closedir(dirp);
- - } while (foundsome); /* keep rereading the directory until it's empty */
- -
- - xxit(0);
- -}
- *-*-END-of-src/inews.c-*-*
- echo x - src/ifuncs.c 1>&2
- sed 's/.//' >src/ifuncs.c <<'*-*-END-of-src/ifuncs.c-*-*'
- -/*
- - * This software is Copyright (c) 1986 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - * ifuncs - functions used by inews.
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)ifuncs.c 2.57 10/29/86";
- -#endif /* SCCSID */
- -
- -#include "iparams.h"
- -#include <errno.h>
- -
- -/*LINTLIBRARY*/
- -
- -#define AFSIZ 4000 /* size of text in the active file for initial malloc */
- -
- -/*
- - * Transmit this article to all interested systems.
- - */
- -
- -#ifdef u370
- -static struct srec srec;
- -#endif /* u370 */
- -
- -static struct hbuf h, hh;
- -
- -#ifdef MULTICAST
- -#define MAXMCAST 20
- -#define MAXMCS 10
- -
- -struct multicast {
- - char mc_name[SBUFLEN]; /* "multi-cast" name */
- - short mc_syscnt;
- - char mc_tosys[MAXMCAST][SBUFLEN];
- -} mcast[MAXMCS];
- -
- -static int mccount;
- -#endif /* MULTICAST */
- -
- -#ifndef DBM
- -char *histfile();
- -#endif /* !DBM */
- -
- -#ifdef VMS
- -/*
- - * For VMS/Eunice there are no links: article was moved to firstbufname
- - * before broadcast is reached. So we read it from there.
- - */
- -extern char firstbufname[];
- -#endif
- -
- -broadcast()
- -{
- - register char *hptr;
- - register char *sptr;
- - register FILE *fp;
- -#ifndef u370
- - struct srec srec;
- -#endif
- - char sentbuf[LBUFLEN];
- - int nsent = 0;
- - char *sentsys;
- -
- - /* h is a local copy of the header we can scribble on */
- -#ifdef VMS
- - fp = xfopen (firstbufname, "r");
- -#else
- - fp = xfopen(ARTICLE, "r");
- -#endif
- - if (hread(&h, fp, TRUE) == NULL)
- - xerror("Cannot reread article");
- - (void) fclose(fp);
- -
- - (void) strcpy(sentbuf, h.ident);
- - (void) strcat(sentbuf, " sent to ");
- - sentsys = index(sentbuf, 0);
- - nsent = 0;
- - /* break path into list of systems. */
- - sptr = hptr = h.path;
- - while ((hptr=strpbrk(hptr, NETCHRS)) != NULL) {
- - *hptr++ = '\0';
- - sptr = hptr;
- - }
- - *sptr = '\0';
- -
- -#ifdef MULTICAST
- - mccount = 0;
- -#endif /* MULTICAST */
- -
- - /* loop once per system. */
- - s_openr();
- - while (s_read(&srec)) {
- - char *dist = h.distribution;
- -#ifdef HIDDENNET
- - if (strncmp(srec.s_name, LOCALSYSNAME, SNLN) == 0)
- - continue;
- -#endif /* HIDDENNET */
- - if (strncmp(srec.s_name, FULLSYSNAME, SNLN) == 0)
- - continue;
- - if (sptr = srec.s_nosend) {
- - while (*sptr) {
- - while (*sptr && *sptr != ',')
- - sptr++;
- - if (*sptr == ',')
- - *sptr++ = '\0';
- - }
- - *++sptr = '\0';
- - }
- - hptr = h.path;
- - while (*hptr != '\0') {
- - if (strncmp(srec.s_name, hptr, SNLN) == 0)
- - goto contin;
- - if (sptr = srec.s_nosend) {
- - while (*sptr != '\0') {
- - if (strncmp(sptr, hptr, SNLN) == 0)
- - goto contin;
- - while (*sptr++)
- - ;
- - }
- - }
- - while (*hptr++ != '\0')
- - ;
- - }
- - if (!ngmatch(h.nbuf, srec.s_nbuf))
- - continue;
- - if (*dist == '\0')
- - dist = "world";
- - if (!ngmatch(dist, srec.s_nbuf) && !ngmatch(srec.s_nbuf, dist))
- - continue;
- -
- - if (nsent) {
- - hptr = sentsys;
- - while ((sptr = index(hptr, ',')) != NULL) {
- - *sptr = '\0';
- - if (strcmp(hptr, srec.s_name) == 0) {
- - *sptr = ',';
- - goto contin;
- - }
- - *sptr++ = ',';
- - for (hptr = sptr; isspace(*hptr); hptr++)
- - ;
- - }
- - if (strcmp(hptr, srec.s_name) == 0)
- - continue;
- - }
- - /* now we've found a system to send this article to */
- -#ifdef MULTICAST
- - if (index(srec.s_flags, 'M')) {
- - /* do a "multi-cast" transmit */
- - register struct multicast *m;
- -
- - if (strlen(srec.s_name) >= SBUFLEN ||
- - strlen(srec.s_xmit) >= SBUFLEN)
- - xerror("system name too long for multicast");
- - for (m = mcast; m < &mcast[mccount]; m++)
- - if (strcmp(srec.s_xmit, m->mc_name) == 0)
- - break;
- - if (m >= &mcast[MAXMCS])
- - xerror("Too many multicasts");
- - if (m == &mcast[mccount]) {
- - mccount++;
- - m->mc_syscnt = 0;
- - strcpy(m->mc_name, srec.s_xmit);
- - }
- - if (m->mc_syscnt >= MAXMCAST)
- - xerror("Too many systems for multicast");
- - strcpy(m->mc_tosys[m->mc_syscnt++], srec.s_name);
- - } else {
- - register struct multicast *m;
- - register char **yptr;
- - char *sysptrs[MAXMCAST];
- - int mc;
- -
- - mc = 0;
- - for (m = mcast; m < &mcast[mccount]; m++)
- - if (strcmp(m->mc_name, srec.s_name) == 0) {
- - yptr = sysptrs;
- - while (mc < m->mc_syscnt)
- - *yptr++ = m->mc_tosys[mc++];
- - break;
- - }
- -#ifdef VMS
- - if (!transmit(&srec, xfopen(firstbufname,"r"), 1,
- - sysptrs, mc))
- -#else /* !VMS */
- - if (!transmit(&srec, xfopen(ARTICLE,"r"), 1, sysptrs,
- - mc))
- -#endif /* !VMS */
- - continue;
- - }
- -#else /* !MULTICAST */
- -#ifdef VMS
- - if (!transmit(&srec, xfopen(firstbufname, "r"),
- -#else /* !VMS */
- - if (!transmit(&srec, xfopen(ARTICLE, "r"),
- -#endif /* !VMS */
- - (strncmp(h.nbuf, "to.", 3) != 0),
- - (char **) NULL, FALSE))
- - continue;
- -#endif /* !MULTICAST */
- - if (nsent)
- - (void) strcat(sentbuf, ", ");
- - (void) strcat(sentbuf, srec.s_name);
- - nsent++;
- - contin:;
- - }
- - if (nsent)
- - log(sentbuf);
- - s_close();
- -}
- -
- -/*
- - * Transmit file to system.
- - */
- -#define PROC 0004
- -#ifndef MULTICAST
- -/* ARGSUSED */
- -#endif /* !MULTICAST */
- -transmit(sp, ifp, maynotify, sysnames, mc)
- -register struct srec *sp;
- -register FILE *ifp;
- -int maynotify;
- -char **sysnames;
- -int mc;
- -{
- - register FILE *ofp;
- - register int c;
- - register char *ptr;
- - char TRANS[BUFLEN];
- - char *argv[20];
- - register int pid;
- - extern char firstbufname[];
- -
- -/* A: afmt: the other machine runs an A news, so we xmit in A format */
- - int afmt = (index(sp->s_flags, 'A') != NULL);
- -/* B: use B format (this is the default - don't use this letter elsewise). */
- -/* F: append name to file */
- - int appfile = (index(sp->s_flags, 'F') != NULL);
- -/* L: local: don't send the article unless it was generated locally */
- - int local = ((ptr = index(sp->s_flags, 'L')) != NULL);
- -/* H: interpolate history line into command, use existing file */
- - int history = (index(sp->s_flags, 'H') != NULL);
- -/* m: moderated: only send if group is moderated */
- - int sendifmoderated = (index(sp->s_flags, 'm') != NULL);
- -/* u: unmoderated: only send if group is unmoderated */
- - int sendifunmoderated = (index(sp->s_flags, 'u') != NULL);
- -/* M: multi-cast: this is taken care of above, but don't reuse flag */
- -#ifdef MULTICAST
- -/* O: multi-cast only, don't send article if not multicast hosts */
- - int multisend = (index(sp->s_flags, 'O') != NULL);
- -#endif /* MULTICAST */
- -/* N: notify: don't send the article, just tell him we have it */
- - int notify = maynotify && (index(sp->s_flags, 'N') != NULL);
- -/* S: noshell: don't fork a shell to execute the xmit command */
- - int noshell = (index(sp->s_flags, 'S') != NULL);
- -/* U: useexist: use the -c option to uux to use the existing copy */
- - int useexist = (index(sp->s_flags, 'U') != NULL);
- -/* I: append messageid to file. implies F flag */
- - int appmsgid = maynotify && (index(sp->s_flags, 'I') != NULL);
- -
- - if (notify)
- - appfile = appmsgid = FALSE;
- -
- - if (!appfile)
- - appfile = appmsgid;
- -
- - if (local && mode == PROC) {
- - local = 0;
- - while (isdigit(*++ptr))
- - local = local * 10 + *ptr - '0';
- - for (ptr = h.path; *ptr != '\0' && local >= 0; local--)
- - while (*ptr++ != '\0')
- - ;
- - if (local < 0) {
- - (void) fclose(ifp);
- - return FALSE;
- - }
- - }
- -
- - /*
- - ** Do not transmit to system specified in -x flag.
- - */
- - if (not_here[0] && strcmp(not_here, sp->s_name) == 0) {
- - (void) fclose(ifp);
- - return FALSE;
- - }
- -
- -#ifdef DEBUG
- - printf("Transmitting to '%s'\n", sp->s_name);
- -#endif /* DEBUG */
- -
- -#ifdef MULTICAST
- - if (multisend && mc == 0) {
- - (void) fclose(ifp);
- - return FALSE;
- - }
- -#endif /* MULTICAST */
- -
- - if ((sendifmoderated && is_mod[0] == '\0') ||
- - (sendifunmoderated && is_mod[0] != '\0')) {
- - fclose(ifp);
- - return FALSE;
- - }
- -
- - if (appmsgid || (!appfile && !useexist && !history)) {
- - if (!hread(&hh, ifp, TRUE)) {
- - logerr("Bad header, not transmitting %s re %s to %s",
- - hh.ident, hh.title, sp->s_name);
- - (void) fclose(ifp);
- - return FALSE;
- - }
- - if (hh.nbuf[0] == '\0') {
- - fprintf(stderr, "Article not subscribed to by %s\n", sp->s_name);
- - (void) fclose(ifp);
- - return FALSE;
- - }
- - (void) sprintf(TRANS, "%s/trXXXXXX", SPOOL);
- - }
- -
- - if (notify) {
- - char oldid[50];
- - (void) sprintf(hh.title, "ihave %s %s", hh.ident, FULLSYSNAME);
- - (void) strcpy(hh.ctlmsg, hh.title);
- - (void) strcpy(hh.numlines, "0");
- - (void) sprintf(hh.nbuf, "to.%s.ctl", sp->s_name);
- - (void) strcpy(oldid, hh.ident);
- - getident(&hh);
- - log("tell %s about %s, notif. id %s",
- - sp->s_name, oldid, hh.ident);
- - }
- -
- - if (appfile) {
- - if (firstbufname[0] == '\0') {
- - extern char histline[];
- - localize("junk");
- - savehist(histline);
- - xerror("No file name to xmit from");
- - }
- - if (sp->s_xmit[0] == '\0')
- - sprintf(sp->s_xmit, "%s/%s%s", BATCHDIR, sp->s_name,
- - appmsgid ? ".ihave" : "");
- -#ifdef IHCC
- - (void) sprintf(TRANS, "%s/%s/%s", logdir(HOME), BATCHDIR, sp->s_xmit);
- - ofp = fopen(TRANS, "a");
- -#else /* !IHCC */
- - ofp = fopen(sp->s_xmit, "a");
- -#endif /* !IHCC */
- - if (ofp == NULL)
- - xerror("Cannot append to %s", sp->s_xmit);
- - fprintf(ofp, "%s", appmsgid ? hh.ident : firstbufname);
- -#ifdef MULTICAST
- - while (--mc >= 0)
- - fprintf(ofp, " %s", *sysnames++);
- -#endif /* !MULTICAST */
- - putc('\n', ofp);
- - (void) fclose(ofp);
- - (void) fclose(ifp);
- - return TRUE;
- - }
- - else if (useexist) {
- - if (firstbufname[0] == '\0')
- - xerror("No file name to xmit from");
- - if (*sp->s_xmit == '\0')
- -#ifdef UXMIT
- - (void) sprintf(bfr, UXMIT, sp->s_name, firstbufname);
- -#else
- - xerror("UXMIT not defined for U flag");
- -#endif
- - else
- -#ifdef MULTICAST
- - makeargs(bfr, sp->s_xmit, firstbufname, sysnames, mc);
- -#else
- - (void) sprintf(bfr, sp->s_xmit, firstbufname);
- -#endif
- - (void) fclose(ifp);
- - } else if (history) {
- - extern char histline[];
- -
- - if (*sp->s_xmit == '\0')
- - xerror("no xmit command with H flag");
- -#ifdef MULTICAST
- - makeargs(bfr, sp->s_xmit, histline, sysnames, mc);
- -#else
- - (void) sprintf(bfr, sp->s_xmit, histline);
- -#endif
- - } else {
- - ofp = xfopen(mktemp(TRANS), "w");
- - if (afmt) {
- -#ifdef OLD
- - fprintf(ofp, "A%s\n%s\n%s!%s\n%s\n%s\n", oident(hh.ident), hh.nbuf, FULLSYSNAME,
- - hh.path, hh.subdate, hh.title);
- -#else /* !OLD */
- - logerr("Must have OLD defined to use A flag for xmit");
- - return FALSE;
- -#endif /* !OLD */
- - } else
- - hwrite(&hh, ofp);
- - if (!notify)
- - while ((c = getc(ifp)) != EOF)
- - putc(c, ofp);
- - if (ferror(ofp))
- - xerror("write failed on transmit");
- - (void) fclose(ifp);
- - (void) fclose(ofp);
- - if (*sp->s_xmit == '\0')
- - (void) sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
- - else
- -#ifdef MULTICAST
- - makeargs(bfr, sp->s_xmit, TRANS, sysnames, mc);
- -#else /* !MULTICAST */
- - (void) sprintf(bfr, sp->s_xmit, TRANS);
- -#endif /* !MULTICAST */
- - }
- -
- - /* At this point, the command to be executed is in bfr. */
- - if (noshell) {
- - if (pid = vfork())
- - fwait(pid);
- - else {
- - (void) close(0);
- - (void) open(TRANS, 0);
- - ptr = bfr;
- - for (pid = 0; pid < 19; pid++) {
- - while (isspace(*ptr))
- - *ptr++ = 0;
- - argv[pid] = ptr;
- - while (!isspace(*++ptr) && *ptr)
- - ;
- - if (!*ptr)
- - break;
- - }
- - argv[++pid] = 0;
- - (void) setgid(gid);
- - (void) setuid(uid);
- - execv(argv[0], argv);
- - xerror("Can't execv %s", argv[0]);
- - }
- - } else {
- - if (!history && sp->s_xmit[0] && !index(bfr, '<')) {
- - char newcmd[LBUFLEN];
- -
- - (void) sprintf(newcmd, "(%s) <%s", bfr,
- - useexist ? firstbufname : TRANS);
- - system(newcmd);
- - } else
- - system(bfr);
- - }
- - if (!appfile && !useexist && !history)
- - (void) unlink(TRANS);
- - (void) fclose(ifp);
- - return TRUE;
- -}
- -
- -#ifdef MULTICAST
- -makeargs(buf, cmd, arg2, sysargs, sac)
- -char *buf;
- -char *cmd;
- -char *arg2;
- -register char **sysargs;
- -int sac;
- -{
- - register char *p = cmd;
- - register char *q;
- - register ac = 0;
- - register char *b = buf;
- -
- - q = p;
- - do {
- - if (q = index(q, ' '))
- - *q = '\0';
- - if (index(p, '%')) {
- - switch (++ac) {
- - case 1:
- - while (--sac >= 0) {
- - sprintf(b, p, *sysargs++);
- - b = index(b, '\0');
- - }
- - break;
- - case 2:
- - sprintf(b, p, arg2);
- - b = index(b, '\0');
- - break;
- - default:
- - if (q)
- - *q = ' ';
- - xerror("badly formed command: %s", cmd);
- - }
- - } else {
- - strcpy(b, p);
- - b = index(b, '\0');
- - }
- - if (q) {
- - *q = ' ';
- - p = q;
- - while (isspace(*q))
- - q++;
- - }
- - } while (q != NULL);
- -}
- -#endif /* MULTICAST */
- -
- -typedef struct {
- - char *dptr;
- - int dsize;
- -} datum;
- -
- -/*
- - * Return TRUE if we have seen this file before, else FALSE.
- - */
- -history(hp)
- -struct hbuf *hp;
- -{
- -#ifdef DBM
- - datum lhs, rhs;
- - datum fetch();
- -#else /* !DBM */
- - register FILE *hfp;
- - register char *p;
- -#endif /* !DBM */
- - char lcident[BUFLEN];
- - extern char histline[];
- -
- -#ifdef DEBUG
- - fprintf(stderr,"history(%s)\n", hp->ident);
- -#endif /* DEBUG */
- - /*
- - * Make the article ID case insensitive.
- - */
- - (void) strcpy(lcident, hp->ident);
- - lcase(lcident);
- -
- - idlock(lcident);
- -#ifdef DBM
- - initdbm(ARTFILE);
- - lhs.dptr = lcident;
- - lhs.dsize = strlen(lhs.dptr) + 1;
- - rhs = fetch(lhs);
- - if (rhs.dptr)
- - return(TRUE);
- -#else /* !DBM */
- - hfp = xfopen(histfile(lcident), "r");
- - while (fgets(bfr, BUFLEN, hfp) != NULL) {
- - p = index(bfr, '\t');
- - if (p == NULL)
- - p = index(bfr, '\n');
- - if (p != NULL) /* can happen if nulls in file */
- - *p = 0;
- - lcase(bfr);
- -
- - if (strcmp(bfr, lcident) == 0) {
- - (void) fclose(hfp);
- - idunlock();
- -#ifdef DEBUG
- - fprintf(stderr,"history returns true\n");
- -#endif /* DEBUG */
- - return TRUE;
- - }
- - }
- - (void) fclose(hfp);
- -#endif /* !DBM */
- - histline[0] = '\0';
- - addhist(hp->ident);
- - addhist("\t");
- -#ifdef DEBUG
- - fprintf(stderr,"history returns false\n");
- -#endif
- - return FALSE;
- -}
- -
- -char histline[PATHLEN];
- -
- -addhist(msg)
- -char *msg;
- -{
- - (void) strcat(histline, msg);
- -}
- -
- -savehist(hline)
- -char *hline;
- -{
- - register FILE *hfp;
- - datum lhs, rhs;
- - long fpos;
- - register char *p;
- -
- - hfp = xfopen(ARTFILE, "a");
- - (void) fseek(hfp, 0L, 2); /* Unisoft 5.1 doesn't seek to EOF on 'a' */
- - fpos = ftell(hfp);
- - fprintf(hfp, "%s\n", hline);
- - (void) fclose(hfp);
- -#ifdef DBM
- - /* We assume that history has already been called, calling dbminit. */
- - p = index(hline, '\t');
- - if (p)
- - *p = 0;
- - lcase(hline);
- - lhs.dptr = hline;
- - lhs.dsize = strlen(lhs.dptr) + 1;
- - rhs.dptr = (char *)&fpos;
- - rhs.dsize = sizeof fpos;
- - store(lhs, rhs);
- -#else /* !DBM */
- - /* also append to proper history subfile */
- - hfp = xfopen(histfile(hline), "a");
- - fprintf(hfp, "%s\n", hline);
- - (void) fclose(hfp);
- -#endif /* !DBM */
- - idunlock();
- -}
- -
- -/*
- - * Save partial news.
- - */
- -/* ARGSUSED */
- -newssave(fd, dummy)
- -FILE *fd;
- -char *dummy;
- -{
- - register FILE *tofd, *fromfd;
- - char sfname[BUFLEN];
- - register int c;
- - time_t tim;
- -
- - if (fd == NULL)
- - fromfd = xfopen(INFILE, "r");
- - else
- - fromfd = fd;
- - (void) umask(savmask);
- - (void) setgid(gid);
- - (void) setuid(uid);
- -
- - (void) sprintf(sfname, "%s/%s", userhome, PARTIAL);
- - if ((tofd = fopen(sfname, "a")) == NULL)
- - xerror("Cannot save partial news in %s", sfname);
- - (void) time(&tim);
- - fprintf(tofd, "----- News saved at %s\n", arpadate(&tim));
- - while ((c = getc(fromfd)) != EOF)
- - putc(c, tofd);
- - (void) fclose(fromfd);
- - (void) fclose(tofd);
- - printf("News saved in %s\n", sfname);
- - xxit(1);
- -}
- -
- -/*
- - * Handle dates in header.
- - */
- -
- -dates(hp)
- -struct hbuf *hp;
- -{
- - time_t edt;
- -
- - if (*hp->subdate) {
- - if (cgtdate(hp->subdate) < 0) {
- - error("Cannot parse submittal date '%s'", hp->subdate);
- - }
- - } else {
- - (void) time(&edt);
- - (void) strcpy(hp->subdate, arpadate(&edt));
- - }
- -}
- -
- -#define LOCKSIZE 128
- -char lockname[LOCKSIZE];
- -
- -idlock(str)
- -char *str;
- -{
- - register int i;
- - register char *cp, *scp;
- - char tempname[LOCKSIZE];
- - time_t now;
- - struct stat sbuf;
- - extern int errno;
- -#ifdef VMS
- - int fd;
- -
- - (void) sprintf(lockname, "/tmp/%s.l.1", str);
- - while ((fd = creat(lockname, 0444)) < 0) {
- -#else /* !VMS */
- - (void) strcpy(tempname, "/tmp/LTMP.XXXXXX");
- - (void) mktemp(tempname);
- - (void) strcpy(lockname, "/tmp/L");
- - i = strlen(lockname);
- - cp = &lockname[i];
- - scp = str - 1;
- - while (i++ < LOCKSIZE && *++scp != '\0')
- - if (*scp == '/') /* slash screws up the open */
- - *cp++ = '.';
- - else
- - *cp++ = *scp;
- - *cp = '\0';
- -#ifdef FOURTEENMAX
- - lockname[5 /* /tmp/ */ + 14] = '\0';
- -#endif
- - i = creat(tempname, 0666);
- - if (i < 0)
- - xerror("Cannot creat %s: errno %d", tempname, errno);
- - (void) close(i);
- - while (link(tempname, lockname)) {
- -#endif /* !VMS */
- - (void) time(&now);
- - if (stat(lockname, &sbuf) < 0)
- - xerror("Directory permission problem in /tmp");
- -
- - if (sbuf.st_mtime + 10*60 < now) {
- - (void) unlink(lockname);
- - logerr("Article %s locked up", str);
- - break;
- - }
- - log("waiting on lock for %s", lockname);
- - sleep((unsigned)60);
- - }
- -#ifdef VMS
- - (void) close(fd);
- -#endif
- - (void) unlink(tempname);
- -}
- -
- -idunlock()
- -{
- - (void) unlink(lockname);
- -}
- -
- -/*
- - * Put a unique name into header.ident.
- - */
- -getident(hp)
- -struct hbuf *hp;
- -{
- - long seqn;
- - register FILE *fp;
- -
- - lock();
- - fp = xfopen(SEQFILE, "r");
- - (void) fgets(bfr, BUFLEN, fp);
- - (void) fclose(fp);
- - seqn = atol(bfr) + 1;
- -/*
- - * For Eunice, this breaks if SEQFILE is not in Unix format.
- - */
- - fp = xfopen(SEQFILE, "r+w");
- - fprintf(fp, "%ld\n", seqn);
- - (void) fclose(fp);
- - unlock();
- -#ifdef HIDDENNET
- - if (strcmp(LOCALSYSNAME, FULLSYSNAME))
- - (void) sprintf(hp->ident, "<%ld@%s.%s%s>", seqn, LOCALSYSNAME, FULLSYSNAME,
- - MYDOMAIN);
- - else
- -#endif /* !HIDDENNET */
- - (void) sprintf(hp->ident, "<%ld@%s%s>", seqn, FULLSYSNAME, MYDOMAIN);
- -}
- -
- -/*
- - * Check that header.nbuf contains only valid newsgroup names;
- - * exit with error if not valid.
- - */
- -ngfcheck(isproc)
- -{
- - register FILE * f;
- - register char * cp;
- - register int i, j;
- - register int ngcount, okcount, havealiased;
- - register int pass;
- - char * ngs[sizeof header.nbuf / 2];
- - char uses[sizeof header.nbuf / 2];
- - char tbuf[sizeof header.nbuf];
- - char abuf[BUFLEN];
- -
- - havealiased = ngcount = 0;
- - is_mod[0] = '\0';
- - /*
- - ** Split header.nbuf into constituent newsgroups.
- - ** Zap "local" newsgroups of articles from remote sites.
- - */
- - cp = tbuf;
- - (void) strcpy(cp, header.nbuf);
- - for ( ; ; ) {
- - while (*cp == NGDELIM || *cp == ' ')
- - ++cp;
- - if (*cp == '\0')
- - break;
- - ngs[ngcount] = cp;
- - do {
- - ++cp;
- - } while (*cp != '\0' && *cp != NGDELIM && *cp != ' ');
- - if (*cp != '\0')
- - *cp++ = '\0';
- - /*
- - ** Check for local only distribution on incoming
- - ** newsgroups. This might occur if someone posted to
- - ** general,net.unix
- - */
- - if (isproc && index(ngs[ngcount], '.') == NULL &&
- - index(header.nbuf, '.') != NULL) {
- - logerr("Local group '%s' removed",
- - ngs[ngcount]);
- - continue;
- - }
- - uses[ngcount] = 1; /* it should go in "Newsgroups" line */
- - ++ngcount;
- - }
- - /*
- - ** Check groups against active file.
- - */
- -recheck:
- - okcount = 0;
- - rewind(actfp); clearerr(actfp);
- - while (okcount < ngcount && fgets(bfr, BUFLEN, actfp) == bfr) {
- - if ((cp = index(bfr, ' ')) == NULL)
- - continue; /* strange line in input! */
- - /* newsgroup 12345 12345 X */
- - /* cp + 01234567890123 */
- - if (!isproc && cp[13] == 'n')
- - continue; /* can't post to this group! */
- - *cp = '\0';
- - for (i = 0; i < ngcount; ++i)
- - if (uses[i] >= 1 && strcmp(bfr, ngs[i]) == 0) {
- - uses[i] = 2; /* it should be localized too */
- - if (cp[13] == 'm')
- - strcpy(is_mod, bfr);
- - ++okcount;
- - }
- - }
- -#ifdef ALWAYSALIAS
- - okcount = 0;
- -#endif /* ALWAYSALIAS */
- - /*
- - ** Handle groups absent from active file.
- - */
- - if (havealiased == 0 && okcount < ngcount) {
- - /*
- - ** See if remaining groups are in our alias list.
- - */
- - f = xfopen(ALIASES, "r");
- - while (okcount < ngcount && fscanf(f, "%s %s", abuf, bfr) == 2)
- - for (i = 0; i < ngcount; ++i) {
- -#ifndef ALWAYSALIAS
- - if (uses[i] == 2)
- - continue;
- -#endif /* ALWAYSALIAS */
- - if (strcmp(ngs[i], abuf) != 0)
- - continue;
- - if (isproc)
- - cp = "Aliased newsgroup %s to %s";
- - else
- - cp = "Please change %s to %s";
- - logerr(cp, abuf, bfr);
- - ngs[i] = AllocCpy(bfr);
- - uses[i] = 2;
- - ++havealiased;
- - ++okcount;
- - }
- - (void) fclose(f);
- - for (i = 0; i < ngcount; ++i) {
- - if (uses[i] == 2)
- - continue;
- - if (isproc)
- - cp = "Unknown newsgroup '%s' not localized";
- - else
- - cp = "Unknown newsgroup '%s'";
- - logerr(cp, ngs[i]);
- -#ifdef ALWAYSALIAS
- - ++okcount; /* so we know to exit below */
- - }
- - if (!isproc && okcount > 0)
- -#else /* !ALWAYSALIAS */
- - }
- - if (!isproc)
- -#endif /* !ALWAYSALIAS */
- - newssave(infp, (char *) NULL);
- - /*
- - * Unfortunately, if you alias an unmoderated group to a
- - * moderated group, you must recheck the active file to see
- - * if the new group is moderated. Rude but necessary.
- - */
- - if (havealiased)
- - goto recheck;
- - }
- - /*
- - ** Zap duplicates.
- - */
- - for (i = 0; i < ngcount - 1; ++i) {
- - if (uses[i] == 0)
- - continue;
- - for (j = i + 1; j < ngcount; ++j) {
- - if (uses[j] == 0)
- - continue;
- - if (strcmp(ngs[i], ngs[j]) != 0)
- - continue;
- - logerr("Duplicate '%s' removed", ngs[j]);
- - if (uses[i] < uses[j])
- - uses[i] = uses[j];
- - uses[j] = 0;
- - }
- - }
- - for (pass = 1; pass <= 2; ++pass) {
- - register int avail;
- -
- - if (pass == 1) {
- - /*
- - ** Rewrite header.nbuf.
- - */
- - cp = header.nbuf;
- - avail = sizeof header.nbuf;
- - } else {
- - /*
- - ** Fill in nbuf.
- - */
- - cp = nbuf;
- - avail = sizeof nbuf;
- - }
- - for (i = 0; i < ngcount; ++i) {
- - if (uses[i] < pass)
- - continue;
- - j = strlen(ngs[i]);
- - if (j + 2 > avail) {
- - logerr("Redone Newsgroups too long");
- - break;
- - }
- - (void) strcpy(cp, ngs[i]);
- - cp += j;
- - *cp++ = (pass == 1) ? NGDELIM : '\0';
- - avail -= (j + 1);
- - }
- - if (pass == 1) {
- - if (cp == header.nbuf)
- - *cp = '\0';
- - else *(cp - 1) = '\0';
- - } else *cp = '\0';
- - }
- - /*
- - ** Free aliases.
- - */
- - for (i = 0; i < ngcount; ++i)
- - if (ngs[i] < tbuf || ngs[i] > &tbuf[sizeof tbuf - 1])
- - free(ngs[i]);
- - return nbuf[0] == '\0';
- -}
- -
- -/*
- - * Figure out who posted the article (which is locally entered).
- - * The results are placed in the header structure hp.
- - */
- -gensender(hp, logname)
- -struct hbuf *hp;
- -char *logname;
- -{
- - register char *fn, *p;
- - char buf[BUFLEN];
- - char *fullname(), *getenv();
- - int fd, n;
- -
- - if ((fn = getenv("NAME")) == NULL) {
- - (void) sprintf(buf, "%s/%s", userhome, ".name");
- - if ((fd = open(buf, 0)) >= 0) {
- - n = read(fd, buf, sizeof buf);
- - (void) close(fd);
- - if (n > 0 && buf[0] >= 'A') {
- - for (p = fn = buf; *p; p++)
- - if (*p < ' ')
- - *p = '\0';
- - }
- - }
- - }
- -
- - if (fn == NULL)
- - fn = fullname(logname);
- -
- - (void) sprintf(hp->path, "%s", logname);
- - (void) sprintf(hp->from, "%s@%s%s (%s)", logname, FULLSYSNAME, MYDOMAIN, fn);
- -}
- -
- -/*
- - * Trap interrupts.
- - */
- -onsig(n)
- -int n;
- -{
- - static int numsigs = 0;
- - /*
- - * Most UNIX systems reset caught signals to SIG_DFL.
- - * This bad design requires that the trap be set again here.
- - * Unfortunately, if the signal recurs before the trap is set,
- - * the program will die, possibly leaving the lock in place.
- - */
- - if (++numsigs > 100) {
- - logerr("inews ran away looping on signal %d", n);
- - xxit(1);
- - }
- - (void) signal(n, onsig);
- - SigTrap = n;
- -}
- -
- -#ifdef BATCH
- -/*
- - * If the stdin begins with "#", we assume we have been fed a batched
- - * shell script which looks like this:
- - * #! rnews 1234
- - * article with 1234 chars
- - * #! rnews 4321
- - * article with 4321 chars
- - *
- - * In this case we just exec the unbatcher and let it unpack and call us back.
- - *
- - * Note that there is a potential security hole here. If the batcher is
- - * /bin/sh, someone could ship you arbitrary stuff to run as shell commands.
- - * The main protection you have is that the effective uid will be news, not
- - * uucp and not the super user. (That, plus the fact that BATCH is set to
- - * "unbatch" as the system is distributed.) If you want to run a batched link
- - * and you are security conscious, do not use /bin/sh as the unbatcher.
- - * the thing to do is to change BATCH in your localize.sh file from /bin/sh
- - * to some restricted shell which can only run rnews.
- - */
- -checkbatch()
- -{
- - int c;
- -
- - c = getc(infp);
- - if (c != EOF)
- - (void) ungetc(c, infp);
- - clearerr(infp);
- - if (c == '#') {
- - char cmd[BUFLEN], unbatcher[BUFLEN], arg1[BUFLEN], arg2[BUFLEN];
- - register char *cp;
- - int n;
- -
- - reset_infp();
- - /*
- - * For efficiency, try and recognize the most common
- - * forms of batching and exec them directly
- - */
- - n = read(0, cmd, BUFLEN-1);
- - if (n <= 0) /* Can't happen */
- - xerror("can't read stdin to unbatch");
- - cmd[n] = '\0';
- - cp = index(cmd, '\n');
- - if (cp)
- - *cp = '\0';
- - /* now put stdin at the "right" place for the exec */
- - (void) lseek(0,1L+(long)(cp - cmd), 0);
- - if( strncmp(cmd, "#! cunbatch", 11) == 0) {
- - (void) strcpy(unbatcher, "/bin/sh");
- - (void) strcpy(arg1, "-c");
- - (void) sprintf(arg2, "%s/compress -d | %s/%s",
- - LIB, LIB, BATCH);
- - } else if (strncmp(cmd, "#! c7unbatch", 12) == 0) {
- - (void) strcpy(unbatcher, "/bin/sh");
- - (void) strcpy(arg1, "-c");
- - (void) sprintf(arg2,
- - "%s/decode | %s/compress -d | %s/%s",
- - LIB, LIB, LIB, BATCH);
- - } else {
- - (void) lseek(0, 0L, 0);
- - (void) sprintf(unbatcher, "%s/%s", LIB, BATCH);
- - arg1[0] = '\0';
- - arg2[0] = '\0';
- - }
- - execl(unbatcher, "news-unpack", arg1, arg2, (char *)0);
- - xerror("Unable to exec %s to unpack news.", unbatcher);
- - }
- -}
- -
- -/*
- - * We've already done a read on stdin, and we want to seek back to the
- - * beginning. We want the real file descriptor (beyond buffers) to
- - * reflect the true beginning. Do whatever is necessary.
- - */
- -reset_infp()
- -{
- - register FILE *ofd;
- - register int c;
- - char *ofdname;
- - long lseek();
- -
- - /* First try to seek back - if so, it's a cheap way back. */
- - if (lseek(0, 0L, 0) == 0L)
- - return;
- -
- - /* Can't seek, so have to copy input to a file and use that. */
- - ofdname = "/tmp/inewsXXXXXX";
- - (void) mktemp(ofdname);
- - ofd = fopen(ofdname, "w");
- - while ((c=getc(infp)) != EOF)
- - putc(c, ofd);
- - if (ferror(ofd))
- - xerror("write failed on temp file %s", ofdname);
- - (void) fclose(ofd);
- - (void) fclose(infp);
- -
- - /* Now for a few lower level hacks to reopen stdin and make
- - * absolutely sure that the right fd's are done for the exec.
- - */
- - (void) close(0); /* make sure stdin is really closed. */
- - (void) open(ofdname, 0);
- - (void) unlink(ofdname); /* to avoid cleaning it up later. */
- -}
- -#endif /* BATCH */
- -
- -/*
- - * Exit and cleanup.
- - */
- -xxit(status)
- -int status;
- -{
- - (void) unlink(INFILE);
- - (void) unlink(ARTICLE);
- - while (lockcount > 0)
- - unlock();
- - idunlock();
- - exit(status);
- -}
- -
- -rwaccess(fname)
- -char *fname;
- -{
- - int fd;
- -
- - fd = open(fname, 2);
- - if (fd < 0)
- - return 0;
- - (void) close(fd);
- - return 1;
- -}
- -
- -exists(fname)
- -char *fname;
- -{
- - int fd;
- -
- - fd = open(fname, 0);
- - if (fd < 0)
- - return 0;
- - (void) close(fd);
- - return 1;
- -}
- -
- -int lockcount = 0; /* no. of times we've called lock */
- -
- -#ifdef VMS
- -
- -#define SUBLOCK "/tmp/netnews.lck.1"
- -
- -/*
- - * Newsystem locking.
- - * These routines are different for VMS because we can not
- - * effectively simulate links, and VMS supports multiple
- - * version numbers of files
- - */
- -lock()
- -{
- - register int i;
- - register int fd;
- -
- - if (lockcount++ == 0) {
- - i = DEADTIME;
- - while ((fd = creat(SUBLOCK, 0444)) < 0) {
- - if (--i < 0) {
- - (void) unlink(SUBLOCK);
- - logerr("News system locked up");
- - }
- - if (i < -3)
- - xerror("Unable to unlock news system");
- - sleep((unsigned)1);
- - }
- - (void) close(fd);
- - }
- -}
- -
- -unlock()
- -{
- - if (--lockcount == 0)
- - (void) unlink(SUBLOCK);
- -}
- -
- -#else /* !VMS */
- -
- -/*
- - * Newsystem locking.
- - */
- -
- -#if defined(BSD4_2) || defined(LOCKF)
- -#ifdef LOCKF
- -#include <unistd.h>
- -#else /* !LOCKF */
- -#include <sys/file.h>
- -#endif /* !LOCKF */
- -static int LockFd = -1;
- -lock()
- -{
- - LockFd = open(SUBFILE,0);
- - /* This will sleep until the other program releases the lock */
- - /* We may need to alarm out of this, but I don't think so */
- -#ifdef LOCKF
- - (void) lockf(LockFd, F_LOCK, 0);
- -#else
- - (void) flock(LockFd, LOCK_EX);
- -#endif
- -}
- -
- -unlock()
- -{
- - (void) close(LockFd);
- -}
- -#else /* !BSD4_2 */
- -lock()
- -{
- - register int i;
- - extern int errno;
- -
- - if (lockcount++ == 0) {
- - i = DEADTIME;
- - while (link(SUBFILE, LOCKFILE)) {
- - if (errno != EEXIST)
- - break;
- - if (--i < 0)
- - xerror("News system locked up");
- - sleep((unsigned)1);
- - }
- - }
- -}
- -
- -unlock()
- -{
- - if (--lockcount == 0)
- - (void) unlink(LOCKFILE);
- -}
- -#endif /* !BSD4_2 */
- -#endif /* !VMS */
- -
- -/*
- - * Generate the name of the person responsible for posting this article,
- - * in order to check that two articles were posted by the same person.
- - */
- -char *
- -senderof(hp)
- -struct hbuf *hp;
- -{
- - register char *r, *q, *tp;
- - char *tailpath();
- -
- - if (hp->sender[0])
- - tp = hp->sender;
- - else if (hp->from[0])
- - tp = hp->from;
- - else
- - tp = tailpath(hp);
- -
- - /* Remove full name */
- - q = index(tp, ' ');
- - if (q)
- - *q = '\0';
- -
- - r = AllocCpy(tp);
- - if (q != NULL)
- - *q = ' ';
- - return r;
- -}
- -
- -/* VARARGS1 */
- -error(message, arg1, arg2, arg3)
- -char *message;
- -long arg1, arg2, arg3;
- -{
- - char buffer[LBUFLEN];
- -
- - fflush(stdout);
- - (void) sprintf(buffer, message, arg1, arg2, arg3);
- - logerr(buffer);
- - xxit(mode == PROC ? 0 : 1);
- -}
- *-*-END-of-src/ifuncs.c-*-*
- echo x - src/patchlevel.h 1>&2
- sed 's/.//' >src/patchlevel.h <<'*-*-END-of-src/patchlevel.h-*-*'
- -0
- *-*-END-of-src/patchlevel.h-*-*
- echo x - src/localize.sh 1>&2
- sed 's/.//' >src/localize.sh <<'*-*-END-of-src/localize.sh-*-*'
- *-*-END-of-src/localize.sh-*-*
- exit
-
-